package zh.dummy.netty.server.util;

import java.util.Collection;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.channel.Channel;
import zh.dummy.netty.core.exception.MessageNullException;
import zh.dummy.netty.core.protocol.NettyMessage;
import zh.dummy.netty.server.context.NettyManager;
import zh.dummy.netty.server.context.listener.WorkflowListener;
import zh.dummy.netty.server.exception.DestinationNullException;

public class NettyUtil {
	
	private final static Logger logger = LoggerFactory.getLogger("NettyUtil");
	
	private static NettyManager nettyManager;
	
	static{
		nettyManager = NettyManager.getInstance();
	}
	
	public static void sendMessage(String destination,Map<String,Object> message){
		if(message == null || message.isEmpty()){
			throw new MessageNullException("message cannot be null");
		}
		if(destination == null || destination.isEmpty()){
			throw new DestinationNullException("destination cannot be null");
		}
		doSend(destination,message);
	}

	public static void sendMessage(Set<String> destinations,Map<String,Object> message){
		if(message == null || message.isEmpty()){
			throw new MessageNullException("message cannot be null");
		}
		if(destinations == null || destinations.isEmpty()){
			throw new DestinationNullException("destination cannot be null");
		}
		for(String destination : destinations){
			doSend(destination,message);
		}
	}

	public static void sendBroadcast(Map<String,Object> message){
		if(logger.isInfoEnabled()){
			logger.info("send broadcast");
		}
		Set<String> keySet = nettyManager.channelKeySet();
		sendMessage(keySet,message);
	}
	
	private static void doSend(String destination, Map<String, Object> message) {
		Channel channel  = nettyManager.getChannel(destination);
		if(channel == null){
			if(logger.isInfoEnabled()){
				logger.info("cannot find destination : " + destination);
			}
			return;
		}
		if(channel.isActive()){
			if(logger.isInfoEnabled()){
				logger.info("send to {} , message : {}",new Object[]{destination,message.toString()});
			}
			NettyMessage nettyMessage = NettyMessageBuilder.buildWorkflowMessage(message);
			channel.writeAndFlush(nettyMessage);
		}else{
			if(logger.isInfoEnabled()){
				logger.info("channel is not actived");
			}
		}
	}

	public static Collection<? extends WorkflowListener> getListeners() {
		return nettyManager.getListeners();
	}

	public static void putChannel(String id, Channel channel) {
		nettyManager.putChannel(id,channel);
	}

	public static void removeChannel(String id){
		nettyManager.removeChannel(id);
	}

	public static boolean containsChannel(String id) {
		return nettyManager.containsChannel(id);
	}
}